
import _localforage from 'localforage';
import AAA from './AAA';
import { MD5 } from 'crypto-js';

/**
 * 草稿
 * @date 1/24/2024 - 11:46:16 AM
 *
 * @export
 * @interface DraftItem
 */
export interface IDraftItem {
  unique_pwd_md5: string;

  /**
   * 草稿ID
   * @date 1/24/2024 - 11:46:27 AM
   *
   * @type {string}
   */
  draft_id: string;

  /**
   * 草稿标题
   * @date 1/24/2024 - 11:46:33 AM
   *
   * @type {string}
   */
  draft_title: string;

  /**
   * 草稿创建时间
   * @date 1/24/2024 - 11:46:39 AM
   *
   * @type {number}
   */
  timestamp: number;


  /**
   * 草稿短内容/缩略内容
   * @date 1/24/2024 - 11:46:53 AM
   *
   * @type {string}
   */
  draft_breif: string;


  /**
   * 草稿最后修改时间
   * @date 1/24/2024 - 11:47:07 AM
   *
   * @type {number}
   */
  modify_time: number;


  /**
   * 对应文章ID
   * @date 1/24/2024 - 11:47:19 AM
   *
   * @type {?(string | number)}
   */
  article_id?: string | number;
}

/**
 * 草稿详情
 * @date 1/24/2024 - 11:45:51 AM
 *
 * @export
 * @interface DraftDetail
 * @typedef {IDraftDetail}
 * @extends {DraftItem}
 */
export interface IDraftDetail extends IDraftItem {

  /**
   * 草稿内容
   * @date 1/24/2024 - 11:46:09 AM
   *
   * @type {string}
   */
  draft_content: string;
}

let _forage: LocalForage | undefined;

export const getForage = async () => {
  const username = await _localforage.getItem<string>('username')
  const forage_name = 'drafts_' + username;
  if (_forage?.config().name === forage_name) return _forage;
  return _forage = _localforage.createInstance({ driver: _localforage.INDEXEDDB, storeName: 'drafts', name: forage_name })
}
export interface save_draft_options {
  draft_id: string,
  draft_title?: string,
  draft_content?: string,
  draft_breif?: string,
  article_id?: string | number,
  pwd?: string,
  unique_pwd?: string,
}
const salt = "assssd32tgb32";

export class PwdNotMatchError extends Error {
  constructor() { super("pwd not match") }
}

export class NotFoundError extends Error {
}

export async function save_draft(
  opts: save_draft_options
): Promise<IDraftItem> {
  const {
    draft_id,
    draft_title = '',
    draft_content = '',
    draft_breif = '',
    article_id,
    pwd = '',
    unique_pwd = '',
  } = opts
  const forage = await getForage();
  const article_drafts = await forage.getItem<IDraftItem[]>("article_drafts") || [];
  const index = article_drafts.findIndex(v => v.draft_id === draft_id);
  const modify_time = new Date().getTime();
  const timestamp = index >= 0 ? article_drafts.splice(index, 1)[0].timestamp : new Date().getTime();
  const unique_pwd_md5 = unique_pwd ? MD5(salt + unique_pwd).toString() : ''
  const draft_item: IDraftItem = {
    draft_id, draft_title, timestamp, draft_breif, modify_time, article_id, unique_pwd_md5
  };
  article_drafts.push(draft_item);
  await forage.setItem<IDraftItem[]>("article_drafts", article_drafts);
  const detail: IDraftDetail = {
    ...draft_item,
    draft_content: AAA.e(draft_content, pwd + unique_pwd),
  }
  await forage.setItem<IDraftDetail>(makeId(draft_id), detail);
  return draft_item;
}
export async function get_draft(draft_id: string, pwd: string, unique_pwd: string): Promise<IDraftDetail | null> {
  const forage = await getForage();
  const ret = await forage.getItem<IDraftDetail>(makeId(draft_id))
  if (!ret) return null
  const unique_pwd_md5 = unique_pwd ? MD5(salt + unique_pwd).toString() : ''
  if (unique_pwd_md5 !== ret?.unique_pwd_md5) throw new PwdNotMatchError()
  ret.draft_content = AAA.d(ret.draft_content, pwd + unique_pwd)
  return ret
}
export async function load_drafts(sortBy: keyof IDraftItem = 'timestamp', decrement: boolean = true): Promise<IDraftItem[]> {
  const forage = await getForage();
  const ret = await forage.getItem<IDraftItem[]>("article_drafts") || []
  if (sortBy) ret.sort((a, b) => (decrement ? 1 : -1) * ((b[sortBy] as any) - (a[sortBy] as any)))
  return ret
}
export async function remove_draft(draft_id: string): Promise<IDraftItem | undefined> {
  const forage = await getForage();
  const drafts = await forage.getItem<IDraftItem[]>("article_drafts") || []
  let pos = drafts.findIndex(v => v.draft_id === draft_id)
  if (pos < 0) throw new NotFoundError("draft not found! id: " + draft_id)

  drafts.splice(pos, 1)
  await forage.setItem<IDraftItem[]>("article_drafts", drafts)
  await forage.removeItem(makeId(draft_id))

  let next_draft: IDraftItem | undefined = void 0
  for (let i = pos; i < drafts.length && !next_draft; ++i)
    if (!drafts[i].unique_pwd_md5) next_draft = drafts[i];
  for (let i = pos - 1; i >= 0 && !next_draft; --i)
    if (!drafts[i].unique_pwd_md5) next_draft = drafts[i];
  return next_draft
}
const makeId = (id: string) => `article_draft_${id}`